package com.xhj.bigfactory.other.stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class StreanTest {
  public static Stream<Character> splitworld(String str) {
    List<Character> characterList = new ArrayList<>();
    for (Character ch : str.toCharArray()) {
      characterList.add(ch);
    }
    return characterList.stream();
  }

  public static List<Character> splitworld2(String str) {
    List<Character> characterList = new ArrayList<>();
    for (Character ch : str.toCharArray()) {
      characterList.add(ch);
    }
    return characterList;
  }

  public static void main(String[] args) {
    Product p1 = new Product(1, "vivoNEX", "手机", "vivo", 3500.0);
    Product p7 = new Product(7, "min9", "手机", "min", 2600.0);
    Product p2 = new Product(2, "球鞋a", "鞋", "乔丹", 800.4);
    Product p5 = new Product(5, "球鞋b", "鞋", "乔丹", 800.4);
    Product p3 = new Product(3, "球鞋", "鞋", "耐克", 600.5);
    Product p4 = new Product(4, "大衣", "上衣", "阿迪", 1200.9);
    Product p6 = new Product(6, "vivoNEX", "手机", "vivo", 3500.0);
    List<Product> products = new ArrayList<Product>();
    products.add(p1);
    products.add(p2);
    products.add(p3);
    products.add(p4);
    products.add(p5);
    products.add(p6);
    products.add(p7);

    String word = "hello world";
    String[] words = word.split(" ");
    List<String> wordList = Arrays.asList(words);
    // ************************创建流
    //		1.通过Collection 系列集合提供的串行流：stream()、并行流： paralleStream()
    List list = new ArrayList();
    // 串行流
    Stream stream1 = list.stream();
    // 并行流
    Stream parallelStream = list.parallelStream();
    //      2.通过Arrays中的静态方法stream(T[] array) 获取数组流
    String[] s = new String[10];
    Stream<String> stream3 = Arrays.stream(s);
    //		3. 通过Stream类中的静态方法 of()
    Stream<String> stream4 = Stream.of("a", "b", "c");
    //      4.使用Stream类的静态方法 iterate 创建无限流
    // Stream<T> iterate(final T seed, final UnaryOperator<T> f)
    // 参数 seed 种子起始值，
    // UnaryOperator 函数式接口 继承Function<T,T> 此时参数类型符合返回值类型一致
    Stream<Integer> iterate = Stream.iterate(0, x -> x += 2);
    // iterate.limit(6).forEach(System.out::println);
    //		5. 使用Stream类的静态方法 generate创建无限流
    //// 参数为Supplier<T> 供给型接口
    Stream<Object> generate = Stream.generate(() -> Math.random());
    // generate.limit(5).forEach(System.out::println);

    /**********************用Stream中间操作**********************/

    /*一个中间操作链，用Stream API 对数据源数据进行操作处理

    注意点：

        若只有中间操作，则不会执行
        只有终止操作执行后，所有的中间操作一次执行，此时就称为延迟加载或者惰性求值*/

    /*****过滤*****/
    // 筛选品牌 是vivo的所有
    //	     products.stream().filter(s -> s.getBrand().equals("vivo"))
    // 筛选品牌 是vivo的手机
    //	    Stream<Product> filter = products.stream().filter(a ->
    // a.getBrand().equals("vivo")&&a.getCategory().equals("手机"));

    /**
     * map映射 <R> Stream<R> map(Function<? super T, ? extends R> mapper) - 接收Lambda，将元素转换成其他形式或提取信息。
     * - 接收一个Function<? super T, ? extends R> mapper函数作为参数，该函数会被应用到每个元素上，并将其映射到一个新的元素。*
     */
    //	    wordist.stream().map(a ->splitworld2(a)).forEach(System.out::println);
    //	    long count = wordist.stream().map(a ->splitworld(a)).count();
    //	    System.out.println(count);
    //	    wordist.stream().map(StreanTest::splitworld).forEach(System.out::println);

    /**
     * flatMap映射 接收一个函数作为参数，将流中的每个值都转换成另一个流，然后把所有流连接成一个流。每个部分流中的每个值成单独小流，再串成一个整体流。
     *
     * <p>对比map映射： 1. map映射是将集合中的部分流添加到整体流中，而flatMap映射是将集合中的部分流中的每个元素单独一个个地添加到整体流中。 2. map映射:
     * Stream<Stream<Character>> , flatMap映射：Stream<Character> *
     */
    //	    wordist.stream().flatMap(a ->splitworld(a)).forEach(System.out::println);
    //	    wordist.stream().flatMap(a ->splitworld2(a).stream()).forEach(System.out::println);
    //	    long count2 = wordist.stream().flatMap(a ->splitworld(a)).count();
    //	    System.out.println(count2);

    /*********排序********/

    /** 自然排序 sorted() 自然排序(Comparable方式)，按照字典顺序进行排序 按照实现的Comparable中的compare to()方法* */
    //	    wordist.stream().flatMap(a ->splitworld(a)).sorted().forEach(System.out::print);
    // product类要实现Comparable接口并重新compareTo方法
    //	    products.stream().sorted().forEach(System.out::println);

    /** 指定排序 sorted(Comparator com) 根据实现Comparator接口的指定方法进行排序* */
    // 默认升序：
    //	    products.stream().sorted(Comparator.comparing(a ->
    // a.getPrice())).forEach(System.out::println);
    //	    products.stream().sorted((a,b)->Double.compare(a.getPrice(),
    // b.getPrice())).forEach(System.out::println);
    /*products.stream().sorted((a,b) ->{if(a.getPrice()==b.getPrice()){
      	return a.getId().compareTo(b.getId());
      }else{
      	return b.getPrice().compareTo(a.getPrice());
      }
    }).forEach(System.out::println);*/
    // 降序：.comparing().reversed()
    //
    // products.stream().sorted(Comparator.comparing(Product::getPrice).reversed()).forEach(System.out::println);
    // 多排序（1  可以先按a升序再按b倒序）a要放到b的后面
    //		.sorted(Comparator.comparing(Product::getId).reversed())
    //	    .sorted(Comparator.comparing(Product::getPrice))//根据价格排序 默认升序 降序：.reversed()
    // 多排序（2）
    //	    .sorted(Comparator.comparing(a ->a.getPrice()+a.getId()))

    /***************** 终止Stream操作：终止操作，执行中间链操作，并产生结果  ************/

    /******** 查找与匹配************/

    /***匹配 match 利用断言型函数接口，返回boolean值 是否匹配
     * 查找返回容器类 Optional类型 避免空指针异常***/

    // allMach()是否所有的元素都符合匹配条件
    //	    System.out.println(products.stream().allMatch(a ->a.getPrice()>500));
    // allMach()是否至少有一个元素满足匹配条件
    //	    System.out.println(products.stream().anyMatch(a ->a.getPrice()>20000));
    // noneMatch-是否所有元素都不符合匹配条件
    //	    System.out.println(products.stream().noneMatch(a ->a.getPrice()>20000));

    /***查找***/

    // .findFirst()-找流中的第一个
    //	    Optional<Product> findFirst = products.stream().findFirst();
    //	    System.out.println(findFirst.get());
    // .findAny()-找流中的任一个？好像就是第一个
    //	    Optional<Product> findAny = products.stream().filter(c ->
    // c.getCategory().equals("鞋")).findAny();
    //	    System.out.println(findAny);
    //	    Optional<Product> findAny2 = products.stream().filter(c ->
    // c.getCategory().equals("鞋")).findAny();
    //	    System.out.println(findAny2);
    // .count()-返回流中元素总个数
    //	    long count = products.stream().count();
    //	    System.out.println(count);
    // .max()-返回流中的最大值
    //	    Optional<Product> max = products.stream().max(Comparator.comparing(a -> a.getPrice()));
    //	    Optional<Product> max2 = products.stream().max(Comparator.comparing(a ->
    // a.getPrice()+a.getId()));
    //	    System.out.println(max2.get());
    // .min()-返回流中的最大值
    //	    Optional<Product> min = products.stream().min(Comparator.comparing(a -> a.getPrice()));
    //	    Optional<Product> min2 = products.stream().min(Comparator.comparing(a ->
    // a.getPrice()+a.getId()));
    //	    System.out.println(min2.get());

    /*********归约与收集*********/

    // .reduce()-将流中元素反复结合起来，得到一个值
    /*List<Integer> ints=Arrays.asList(1,2,3,4);
    Integer reduce = ints.stream().reduce(0, (a,b)->a+b);
    System.out.println(reduce);*/
    // Optional<Double> reduce = products.stream().map(Product::getPrice).reduce(Double::sum);
    // 求所有商品价格的和
    /*	    Optional<Double> reduce = products.stream().map(Product::getPrice).reduce((a,b)->a+b);
    Optional<Double> reduce2 = products.stream().filter(a ->a.getPrice()>10000).map(Product::getPrice).reduce((a,b)->a+b);
    System.out.println(reduce.get());
    System.out.println(reduce2);*/

    /******  collect-将流转换为其他形式
     *接收一个Collector接口的实现，用于Stream中元素做汇总的方法
     *利用Collectors实用工具类中提供的很多静态实现Collector接口的方法，进行相应的转换收集操作。**********/

    // 要得到所有的商品名称的集合
    /*List<String> collect = products.stream().map(Product::getName).collect(Collectors.toList());
    collect.forEach(System.out::println);*/
    /* List<String> collect = products.stream().map(Product::getName).distinct().collect(Collectors.toList());
    collect.forEach(System.out::println);*/
    /* Set<String> collect2 = products.stream().map(Product::getName).collect(Collectors.toSet());
    collect2.forEach(System.out::println);*/
    /*   如果想转换成其他没有的现成静态方法的数据结构集合，就使用Collectors.toCollection()方法，该
    方法具体参数和返回值为：Collector<T, ?, C> toCollection(Supplier<C> collectionFactory)*/
    /*Set<String> collect = products.stream().map(Product::getName).collect(Collectors.toCollection(LinkedHashSet::new));
    collect.forEach(System.out::println);*/

    /***********Collectors类中的常用方法**************/
    /** counting-统计数量* */
    //	    Long collect = products.stream().collect(Collectors.counting());
    //	    System.out.println(collect);

    /** averagingDouble-求平均值并转换成Double类型* */
    // 求所有商品价格的平均值
    //	   Double collect = products.stream().collect(Collectors.averagingDouble(Product::getPrice));
    //	   Double collect2 = products.stream().collect(Collectors.averagingDouble(a ->
    // a.getPrice()+a.getId()));
    //	   System.out.println(collect2);

    /** summingDouble-求和并转换成Double类型* */
    //	    Double collect2 = products.stream().collect(Collectors.summingDouble(Product::getPrice));
    //	    System.out.println(collect2);

    /** maxBy/minBy-根据函数条件求此最大/最小值的元素* */
    //	    Optional<Product> collect =
    // products.stream().collect(Collectors.maxBy(Comparator.comparing(a->a.getPrice())));
    //	    System.out.println(collect.get());

    /** groupingBy-分组* */
    // 单分组
    // 以品牌分组
    /*Map<String, List<Product>> collect = products.stream().collect(Collectors.groupingBy(Product::getBrand));
       Set<Entry<String, List<Product>>> entrySet = collect.entrySet();
       for (Entry<String, List<Product>> entry : entrySet) {
    	System.out.println(entry.getKey()+":"+entry.getValue());
    }*/
    // 多分组  （两个参数，第二个参数为Collector，即实现无限分组）
    // 先以类别分组，再以品牌分组
    /*Map<String, Map<String, List<Product>>> collect = products.stream()
      .collect(Collectors.groupingBy(Product::getCategory,Collectors.groupingBy(Product::getBrand)));
    System.out.println(collect);*/

    /** partitioningBy-分区* */
    /*满足条件的分到一个区，不满足条件分到另一个区*/
    //       	 Map<Boolean, List<Product>> collect =
    // products.stream().collect(Collectors.partitioningBy(a -> a.getPrice()>2000));
    /*Set<Entry<Boolean, List<Product>>> entrySet = collect.entrySet();
       for (Entry<Boolean, List<Product>> entry : entrySet) {
    	System.out.println(entry.getKey()+":"+entry.getValue());
    }  */

    /** summarizingDouble-计算方法总汇函数* */
    //		DoubleSummaryStatistics collect =
    // products.stream().collect(Collectors.summarizingDouble(Product::getPrice));
    // 平均值
    //		collect.getAverage();
    // 最大值
    //		collect.getMax();
    // 最小值
    //		collect.getMin();
    // 求和
    //		collect.getSum();
    // 求个数
    //		collect.getCount();

    /** joining-连接字符串* */
    /*String collect = products.stream().map(a->a.getBrand()).collect(Collectors.joining(","));
    System.out.println(collect);*/

  }
}
